Перейти к основному содержимому

Регулярные выражения

Разработчику Аналитику Тестировщику
Архитектору Инженеру

Регулярные выражения

Что такое регулярные выражения?

Алгоритмы порой требуют особого подхода, связанного с определением последовательности символов. Так, мы привыкли к тому, что фраза "кошка" представляет собой всего лишь слово целиком. Для программы же это набор символов, написанных в соответствии с таблицей кодировки: к, о, ш, к, а.

Вам следует понять простое правило - программа всегда работает по более сложному и подробному алгоритму, чем мы привыкли. И поиск нам как раз покажет наглядный пример того, как же всё сложно может быть.

Алгоритм поиска выражений выглядит куда сложнее, чем кажется. Для пользователя это может быть и легко, он просто пишет текст "кошка" в поле поиска, а система сама какими-то махинациями преподносит на блюдечке результат со всеми совпадениями.

Как же определяются такие совпадения? Одно из важных решений - регулярные выражения.

Регулярные выражения (Regular Expressions, сокращённо RegEx) — это последовательность символов, которая задаёт правило поиска строк в тексте. Они поддерживаются почти во всех языках программирования.

Основная цель использования регулярных выражений заключается в автоматизации работы с неструктурированными или частично структурированными текстовыми данными. В отличие от обычного поиска по фиксированному слову, регулярное выражение ищет паттерн, который может варьироваться в зависимости от контекста. Это делает их незаменимыми при обработке больших массивов логов, валидации пользовательского ввода, парсинге веб-страниц и очистке данных перед загрузкой в базы данных.

Синтаксис регулярных выражений строится на комбинации двух типов символов: литералов и метасимволов. Литералы соответствуют самим себе и используются для поиска конкретных букв, цифр или знаков препинания. Метасимволы обладают особым смыслом и управляют логикой поиска, указывая на количество повторений, начало или конец строки, либо классы допустимых символов. Для поиска самих метасимволов как обычных знаков применяется механизм экранирования обратным слэшем (\) или использование сырых строк (raw strings) в коде.

Используются они для валидаций форм (email, пароли, номера телефонов), поиска и замены в логах, автоматизации обработки текстовых файлов, очистки и структурирования данных, проверки корректности ответов.

Синтаксис RegEx состоит из:

  • литералов (обычных цифр, букв);
  • метасимволов (специальных символов с особыми значениями);
  • экранирования спецсимволов с помощью \ или raw-строк r”.

Пример:

Проверка email (проверяет корректность адреса):
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

Примером практического применения служит проверка формата электронной почты. Система должна убедиться, что введенный адрес содержит символ «@», имеет доменную часть и правильное расширение. Регулярное выражение формализует эти требования и гарантирует, что строка начинается с начала (^), содержит допустимые символы локальной части, затем символ «@», доменное имя и заканчивается расширением из двух и более букв.

Другим примером является поиск телефонных номеров в тексте. Паттерн ищет последовательность, начинающуюся с кода страны, пробела, трех цифр, еще одного пробела, трех цифр, дефиса, двух цифр, второго дефиса и последних двух цифр. Такой подход позволяет извлечь контактные данные из огромных массивов неструктурированных сообщений или файлов без необходимости писать сложные циклы и условия вручную.

Поиск телефонного номера:
\+7\s$$\d{3}$$\s\d{3}-\d{2}-\d{2}

Важно: RegEx - довольно сложный инструмент, который пригодится лишь после практики. Рекомендуется к нему вернуться только после того, как на практике встретитесь с необходимостью. Можете поэкспериментировать с ними на различных сервисах, к примеру тут - https://regex101.com/.

Чит-лист - https://cheatsheets.zip/regex


Зачем нужны регулярные выражения?

Валидация данных — это одна из ключевых задач, где регулярные выражения проявляют свою эффективность. При регистрации пользователей системы проверяют корректность введенных паролей, электронных почт, номеров телефонов и дат рождения. Регулярное выражение мгновенно определяет, соответствует ли строка ожидаемому формату, отсекая ошибочные или вредоносные данные на этапе ввода. Это снижает нагрузку на сервер и предотвращает ошибки в базе данных.

Поиск и замена в больших объемах текста требуют гибкости, которую предоставляет только шаблонный поиск. Системы администрирования используют регулярные выражения для массового изменения имен файлов, исправления опечаток в документации или форматирования логов. Вместо ручного перебора тысяч строк оператор задает один шаблон, который система применяет ко всем подходящим участкам текста автоматически.

Извлечение данных (парсинг) часто встречается при работе с веб-страницами, XML или JSON файлами. Если структура документа стабильна, регулярное выражение может выделить конкретные поля, такие как цены, имена авторов или ссылки, игнорируя остальной контент. Это ускоряет процесс сбора информации для аналитики и машинного обучения.

Фильтрация и сортировка потоков данных также опирается на этот инструмент. Утилиты командной строки, такие как grep или sed, используют регулярные выражения для вывода строк, содержащих определенные слова, или для удаления пустых строк из файла. Разработчики применяют их для анализа журналов событий (логов) с целью обнаружения ошибок, подозрительной активности или специфических паттернов поведения системы.

Обработка естественного языка включает задачи токенизации, нормализации и фильтрации текста. Регулярные выражения помогают удалять специальные символы, приводить текст к нижнему регистру, выделять ключевые слова или определять структуру предложений. Это подготовительный этап для работы с алгоритмами машинного обучения и семантического анализа.


Базовые элементы синтаксиса

Литералы представляют собой обычные символы, которые ищутся в точности так, как они записаны. Буквы a и z находят соответствующие буквы в тексте, цифры 0 и 9 ищут числа. Специальные символы, такие как точка или звездочка, в обычном режиме тоже считаются литералами, если они не являются частью специального паттерна.

Метасимволы управляют логикой поиска и определяют поведение шаблона. Символ . находит любой символ, кроме переноса строки. Точки с запятой ^ и $ указывают на начало и конец строки соответственно. Квадратные скобки [] создают класс символов, а круглые скобки () группируют части выражения для захвата результата.

Квантификаторы задают количество повторений предыдущего элемента. Звездочка * означает ноль или более раз, плюс + — одно или более раз, вопросительный знак ? — ноль или один раз. Фигурные скобки {n} указывают ровно n раз, {n,} — n и более раз, а {n,m} — от n до m раз включительно.

Экранирование используется для поиска специальных символов как обычных знаков. Обратный слэш \ перед символом превращает его в литерал. Например, \. ищет точку, а не любой символ. В некоторых языках программирования для создания сырых строк (raw strings) используется префикс r, что избавляет от необходимости двойного экранирования слэшей.

Группировка и захват позволяют сохранить часть найденного текста для дальнейшего использования. Скобки () создают группу, которую можно использовать в обратной ссылке \1, \2 или вернуть результат функции поиска. Это полезно для извлечения отдельных частей сложного паттерна, например, года и месяца из даты.

Отрицательные классы обозначаются символом каретки ^ внутри квадратных скобок. Выражение [^0-9] находит любой символ, который не является цифрой. Это удобно для поиска спецсимволов или пробелов в числовых полях, а также для фильтрации недопустимых данных.

Пересечения и альтернативы расширяют возможности выбора. Символ вертикальной черты | работает как логическое ИЛИ, позволяя выбрать одну из нескольких альтернатив. Выражение cat|dog найдет либо слово «cat», либо слово «dog». Это упрощает создание сложных условий поиска без необходимости писать множество отдельных паттернов.


Примеры регулярных выражений

КомандаЗначениеПример
\dЛюбая цифра (0-9)\d\d → "42"
\wБуква (латиница), цифра или _\w+ → "Hello_123"
\sПробел, табуляция или перенос строки\s+ → " "
.Любой символ (кроме переноса строки)a.c → "abc", "a c"
^Начало строки^Start → "Start..."
$Конец строкиend$ → "...end"
[...]Любой символ из скобок[aeiou] → "a", "e"
[^...]Любой символ, кроме указанных[^0-9] → "a", "!"
(...)Группа символов (для захвата или применения квантификаторов)(\d{3}) → "123"
\Экранирование спецсимволов (чтобы искать их как текст)\. → "."
*0 и более разa* → "", "a", "aaa"
+1 и более разa+ → "a", "aaa"
?0 или 1 разa? → "", "a"
{n}Ровно n разa{3} → "aaa"
{n,}n и более разa{2,} → "aa", "aaaa"
{n,m}От n до m разa{2,4} → "aa", "aaaa"

Валидация электронной почты требует проверки наличия символа «@» между локальной частью и доменом, а также наличия точки и расширения. Шаблон ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ обеспечивает соответствие этим требованиям. Он начинает проверку с начала строки, допускает буквы, цифры и специальные знаки в начале адреса, затем требует символ «@», доменное имя и обязательно точку с двумя или более буквами в конце.

Поиск телефонных номеров в международном формате использует группировку и квантификаторы. Выражение \+7\s(\d{3})\s\d{3}-\d{2}-\d{2} находит номера, начинающиеся с кода страны +7, разделенные пробелами и дефисами. Группировка скобок () позволяет захватить отдельные части номера для дальнейшей обработки или форматирования. Это полезно при сборе контактов из рассылок или баз данных клиентов.

Извлечение URL-адресов из текста осуществляется с помощью паттерна https?:\/\/[^\s]+. Он ищет протоколы http или https, следом двоеточие и две косые черты, а затем любые символы до первого пробела. Такой подход позволяет быстро собрать все ссылки со страницы или из текстового документа, включая те, которые находятся внутри абзацев.

Форматирование дат в различных вариантах (ДД.ММ.ГГГГ, ГГГГ-ММ-ДД, ДД/ММ/ГГГГ) требует гибкого подхода. Выражение \b\d{1,2}[\/\-\.]\d{1,2}[\/\-\.]\d{2,4}\b находит даты с любым разделителем и количеством цифр. Квантификаторы {1,2} и {2,4} позволяют адаптировать поиск под разные стандарты записи времени, что критично при импорте данных из разных источников.

Поиск повторяющихся слов помогает выявить дубликаты в тексте или найти опечатки. Паттерн \b(\w+)\s+\1\b находит слово, за которым сразу следует то же самое слово. Первая группа (\w+) запоминает слово, а \1 ссылается на него. Это эффективно для очистки текстов от случайных повторов, возникающих при наборе или копировании.

Извлечение IP-адресов из сетевых логов выполняется с помощью выражения \b(?:\d{1,3}\.){3}\d{1,3}\b. Оно ищет четыре группы цифр от 1 до 3, разделенные точками. Хотя этот шаблон находит и некорректные адреса (например, 999.999.999.999), он отлично подходит для первичной фильтрации и выделения всех возможных вариантов IP-адресов в потоке данных.

Проверка паролей на сложность часто включает несколько условий одновременно. Выражение ^(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$ требует наличие хотя бы одной заглавной буквы, одной цифры и одного специального символа, а также минимальную длину в 8 символов. Каждый позитивный просмотр (?=...) проверяет отдельное условие, не потребляя символы строки.

Очистка HTML-тегов из текста позволяет получить чистый контент без разметки. Паттерн <[^>]*> находит все теги, начинающиеся с < и заканчивающиеся >, исключая вложенные угловые скобки. Замена найденных совпадений на пустую строку оставляет только видимый текст, что необходимо для индексации или анализа содержимого веб-страниц.

Выделение хештегов в социальных сетях происходит с помощью выражения #\w+. Оно ищет символ решетки, за которым следуют одна или более букв, цифр или знаков подчеркивания. Это простой способ собрать все активные темы из постов, комментариев или твитов для дальнейшего анализа трендов или категоризации контента.

Поиск серийных номеров оборудования часто использует алфавитно-цифровые комбинации с дефисами. Шаблон [A-Z]{3}-\d{4}-[A-Z]{2} находит строки, состоящие из трех букв, дефиса, четырех цифр и двух букв. Такой формат типичен для заводских маркировок, что позволяет автоматически идентифицировать устройства в базах данных инвентаризации.